package ajjj.kiviq.controllers;

import java.io.*;
import ajjj.kiviq.beans.*;
import javax.faces.bean.*;
import javax.faces.context.FacesContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;

/**
 * Manages incoming uploaded files, saves them
 * with auto generated file names and sets
 * the QuestionImage property of the current
 * ManageCategoryBean instance
 * 
 * @author Jonatan Strömsten
 */
@ManagedBean
@RequestScoped
public class FileUploadController {

    @ManagedProperty(value = "#{newCat}")
    private ManageCategoryBean newCat;

    /** Creates a new instance of FileUploadController */
    public FileUploadController() {
    }

    /**
     * Handles uploaded files
     * @param event The FileUploadEvent associated
     * to the file upload event
     */
    public void handleFileUpload(FileUploadEvent event) {
	UploadedFile file = event.getFile();
	try {
	    removeFileIfExists();

	    String relName = saveFile(file);
	    newCat.setQuestionImage(relName);

	} catch (IOException e) {
	    //File was not saved...
	}
    }

    /**
     * Get the ManageCategoryBean associated to this controller
     * @return The ManageCategoryBean
     */
    public ManageCategoryBean getNewCat() {
	return newCat;
    }

    /**
     * Set the ManageCategoryBean associated to this controller
     * @param newCat The ManageCategoryBean
     */
    public void setNewCat(ManageCategoryBean newCat) {
	this.newCat = newCat;
    }

    /**
     * Tries to remove the current file associated
     * to the current ManageCategoryBean
     */
    private void removeFileIfExists() {
	try {
	    newCat.removeQuestionImage();
	} catch (Exception e) {
	    //There was no file
	}
    }

    /**
     * Generates a new file name and saves the incoming
     * file to the "images" folder of the application,
     * keeps the file extension and creates the "images" directory
     * if it does not already exist. If there is a file named "images"
     * in the application directory this method will probably throw
     * an exception
     * 
     * @param file
     * @return The generated relative path to the file, the path
     * is relative to the "images" directory
     * @throws IOException Yes, using java it's nicer to
     * declare the exception being thrown here. Otherwise
     * the finally-clause of the IO handling will be seriously
     * cluttered
     */
    private String saveFile(UploadedFile file)
	    throws IOException {
	String images = FacesContext.getCurrentInstance().getExternalContext().getRealPath("images");
	File f = new File(images);
	if (!f.exists()) {
	    f.mkdir();
	}

	String ext = "";
	int extStart = file.getFileName().indexOf('.');
	if (extStart != -1) {
	    ext = file.getFileName().substring(extStart);
	}

	File newFile;
	String relName = "";
	Long at = 0L;
	do {
	    String sat = String.format("%x", at);
	    at++;
	    relName = "" + sat + ext;
	    newFile = new File(f, relName);

	} while (newFile.exists());

	DataOutputStream out = null;
	try {
	    out = new DataOutputStream(new FileOutputStream(newFile));
	    out.write(file.getContents());

	} finally {
	    if (out != null) {
		out.close();
	    }
	}

	return relName;
    }
}
